package com.zjny.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.zjny.constant.CommonConstant;
import com.zjny.constant.DateConstant;
import com.zjny.constant.DateRegexConstant;
import com.zjny.constant.ToolRegexConstant;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * packageName com.zjny.util
 * 日期工具类
 * 1：获取当前Date型日期{@link DateUtils#getNowDate()}
 * 2：获取当前的日期【yyyy-MM-dd】{@link DateUtils#getDate()}
 * 3: 获取当前的时间【yyyy-MM-dd：hh:mm:ss】{@link DateUtils#getTime()}
 * 4：获取当前时间{@link DateUtils#dateTimeNow(String)}
 * 5：获取日期时间{@link DateUtils#dateTime(Date)}
 * 6：日期时间格式化成字符串{@link DateUtils#parseDateToStr(String, Date)}
 * 7：将指定格式的时间字符串转换为Date对象{@link DateUtils#dateTime(String, String)})}
 * 8: 日期路径【斜线表示法】{@link DateUtils#datePathByObliqueLine()}
 * 9: 日期路径【直接连接】{@link DateUtils#datePathByEmpty()}
 * 10：日期型字符串转化为日期格式{@link DateUtils#parseDate(String)}
 * 11：计算两个日期的相差毫秒数{@link DateUtils#differentDaysByMillisecond(Date, Date)}
 * 12：获取下一天的开始时间{@link DateUtils#getNextDayStartTime()}
 * 13：检查时间大小{@link DateUtils#checkDateSize(Date, Date)}
 * 14：将日期分解成 年、月、日、时、分、秒的int数组，用于发给前台时间{@link DateUtils#splitDate(Date)}
 * 15: 检查给定的时间范围是否已过期{@link DateUtils#checkExpired(String, String)}
 * 16：时间差{@link DateUtils#getDatePoor(Date, Date)}
 * 17：LocalDateTimeToDate{@link DateUtils#localDateTimeToDate(LocalDateTime)}
 * 18：localDateToDate{@link DateUtils#localDateToDate(LocalDate)}
 * 19：1 2 3 -> 1年零2个月零3日{@link DateUtils#getFormatWithNum(int, int, int)}
 * 20：摘取数字从 xx年零xx个月零xx日{@link DateUtils#getDateNumFromDateString(String)}
 * 21：日期格式化成为2022年4月9日的形式{@link DateUtils#doStandard(String)}
 * 22：格式化日期字符串。将日期转成中文形式{@link DateUtils#formatStrToChineseDate(String)}

 *
 * @author cui haida
 * @version JDK 8
 * 2025/6/18
 */
public class DateUtils extends DateUtil {
    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getDate() {
        return dateTimeNow(DateConstant.YYYY_MM_DD);
    }

    /**
     * 获取当前时间, 默认格式为yyyy-MM-dd：hh:mm:ss
     *
     * @return String
     */
    public static String getTime() {
        return dateTimeNow(DateConstant.YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 获取当前时间
     *
     * @param format 指定格式
     * @return 时间字符串
     */
    public static String dateTimeNow(String format) {
        return parseDateToStr(format, new Date());
    }

    /**
     * 获取日期时间
     *
     * @param date 日期
     * @return 时间字符串
     */
    public static String dateTime(Date date) {
        return parseDateToStr(DateConstant.YYYY_MM_DD, date);
    }

    /**
     * 日期时间格式化成字符串
     *
     * @param date   日期时间
     * @param format 指定格式
     * @return 字符串
     */
    public static String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 将指定格式的时间字符串转换为Date对象。
     *
     * @param format 指定的时间格式，例如"yyyy-MM-dd HH:mm:ss"。
     *               该格式必须与待转换时间字符串ts的格式匹配。
     * @param ts     待转换的时间字符串，它应该符合传入的format参数指定的格式。
     * @return 返回一个Date对象，表示解析后的时间。
     * @throws RuntimeException 如果时间字符串无法根据指定格式解析，会抛出运行时异常。
     */
    public static Date dateTime(final String format, final String ts) {
        try {
            // 使用传入的格式解析时间字符串，并返回对应的Date对象
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            // 当解析失败时，抛出运行时异常
            throw new RuntimeException(e);
        }
    }


    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static String datePathByObliqueLine() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static String datePathByEmpty() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期格式
     */
    public static Date parseDate(String str) {
        if (str == null) {
            return null;
        }
        try {
            return parse(str, DateConstant.PARSE_PATTERNS);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 计算两个日期的相差毫秒数
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
    }

    /**
     * 获取下一天的开始时间 00:00:00.000
     *
     * @return long
     */
    public static long getNextDayStartTime() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }

    /**
     * 检查时间大小
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     */
    public static void checkDateSize(Date startTime, Date endTime) {
        if (endTime.before(startTime)) {
            throw new RuntimeException("开始时间不能大于结束时间");
        }
    }

    /**
     * 将日期分解成 年、月、日、时、分、秒的int数组，用于发给前台时间
     *
     * @param date 日期
     * @return 拆分结果
     */
    public static int[] splitDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int[] dates = new int[6];
        dates[0] = c.get(Calendar.YEAR);// 年
        dates[1] = c.get(Calendar.MONTH) + 1;// 月
        dates[2] = c.get(Calendar.DAY_OF_MONTH);// 日
        dates[3] = c.get(Calendar.HOUR_OF_DAY);// 小时
        dates[4] = c.get(Calendar.MINUTE);// 分
        dates[5] = c.get(Calendar.SECOND);// 秒
        return dates;
    }

    /**
     * 检查给定的时间范围是否已过期。
     *
     * @param startTime 开始时间的字符串表示，格式应符合DateUtil.parseDateTime的解析要求。
     * @param endTime   结束时间的字符串表示，格式同上。
     * @return 返回一个布尔值，如果当前时间在开始时间和结束时间之间（包括边界），则返回true；否则返回false。
     */
    public static Boolean checkExpired(String startTime, String endTime) {
        // 将字符串形式的开始时间和结束时间转换为Date类型
        Date start = DateUtil.parseDateTime(startTime);
        Date end = DateUtil.parseDateTime(endTime);
        // 检查开始时间和结束时间的合法性
        checkDateSize(start, end);
        // 判断当前时间是否在指定的时间范围内
        return DateUtil.isIn(DateUtil.date(), start, end);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 增加 LocalDateTime ==> Date
     */
    public static Date localDateTimeToDate(LocalDateTime temporalAccessor) {
        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }

    /**
     * 增加 LocalDate ==> Date
     */
    public static Date localDateToDate(LocalDate temporalAccessor) {
        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
        return localDateTimeToDate(localDateTime);
    }

    /**
     * 1 2 3 -> 1年零2个月零3日
     *
     * @param years  年
     * @param months 月
     * @param days   日
     * @return 转成对应的形式
     */
    public static String getFormatWithNum(int years, int months, int days) {
        if (years == 0) {
            if (months == 0 && days == 0) {
                return CommonConstant.DIGITS[0] + DateConstant.UNIT_DAY;
            } else if (months == 0) {
                return days + DateConstant.UNIT_DAY;
            } else if (days == 0) {
                return months + DateConstant.UNIT_GE + DateConstant.UNIT_MONTH;
            } else {
                return months + DateConstant.UNIT_GE + DateConstant.UNIT_MONTH + CommonConstant.SIMPLE_DIGITS[0] + days + DateConstant.UNIT_DAY;
            }
        } else {
            if (months == 0 && days == 0) {
                return years + DateConstant.UNIT_YEAR;
            } else if (months == 0) {
                return years + DateConstant.UNIT_YEAR + CommonConstant.SIMPLE_DIGITS[0] + days + DateConstant.UNIT_DAY;
            } else if (days == 0) {
                return years + DateConstant.UNIT_YEAR + CommonConstant.SIMPLE_DIGITS[0] + months + DateConstant.UNIT_GE + DateConstant.UNIT_MONTH;
            } else {
                return years + DateConstant.UNIT_YEAR + CommonConstant.SIMPLE_DIGITS[0] + months + DateConstant.UNIT_GE + DateConstant.UNIT_MONTH + CommonConstant.SIMPLE_DIGITS[0] + days + DateConstant.UNIT_DAY;
            }
        }
    }


    /**
     * 摘取数字从 xx年零xx个月零xx日
     *
     * @param date xx年零xx个月零xx日
     * @return map
     */
    public static Map<String, Integer> getDateNumFromDateString(String date) {
        Map<String, Integer> map = new HashMap<>(CommonConstant.MAP_INIT_CAP);
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < date.length(); i++) {
            if (Character.isDigit(date.charAt(i)) && i + 1 < date.length() && !Character.isDigit(date.charAt(i + 1))) {
                stringBuilder.append(date.charAt(i));
                String unit = String.valueOf(date.charAt(i + 1));
                switch (unit) {
                    case DateConstant.UNIT_GE:
                    case DateConstant.UNIT_MONTH:
                        map.put(DateConstant.UNIT_MONTH, Integer.parseInt(stringBuilder.toString()));
                        break;
                    case DateConstant.UNIT_YEAR:
                        map.put(DateConstant.UNIT_YEAR, Integer.parseInt(stringBuilder.toString()));
                        break;
                    case DateConstant.UNIT_DAY:
                        map.put(DateConstant.UNIT_DAY, Integer.parseInt(stringBuilder.toString()));
                        break;
                }
                stringBuilder = new StringBuilder();
            } else if (Character.isDigit(date.charAt(i))) {
                stringBuilder.append(date.charAt(i));
            }
        }
        // 未赋值添加0
        if (!map.containsKey(DateConstant.UNIT_YEAR)) {
            map.put(DateConstant.UNIT_YEAR, 0);
        }
        if (!map.containsKey(DateConstant.UNIT_MONTH)) {
            map.put(DateConstant.UNIT_MONTH, 0);
        }
        if (!map.containsKey(DateConstant.UNIT_DAY)) {
            map.put(DateConstant.UNIT_DAY, 0);
        }

        return map;
    }

    /**
     * 日期标准化，例如：2022-04-09,2022-4-09,2022/4/9,2022/4/09->2022年4月9日
     *
     * @param str 目标要素
     * @return 转化后的要素内容
     */
    private static String chineseDateConvertLine(String str) {
        // 号 -> 日
        str = str.replaceAll(DateConstant.UNIT_HAO, DateConstant.UNIT_DAY);
        // hu tool 标准成为 xxxx-xx-xx
        String dateFormat = formatDate(parse(str));
        // 通过 - 分割，然后得到对应的年月日
        String[] dateSplit = dateFormat.split(CommonConstant.SPLIT_LINE);
        int year = Integer.parseInt(dateSplit[0]);
        int month = Integer.parseInt(dateSplit[1]);
        int day = Integer.parseInt(dateSplit[2]);
        return year + DateConstant.UNIT_YEAR + month + DateConstant.UNIT_MONTH + day + DateConstant.UNIT_DAY;
    }


    /**
     * 格式化日期字符串。将日期转成中文形式
     *
     * @param srcDate 源日期字符串。可能包含空格，需要被去除。
     * @return 格式化后的日期字符串。如果标准化或格式化过程中发生异常，则返回未处理的源字符串。
     */
    public static String formatStrToChineseDate(String srcDate) {
        // 移除字符串中的空格
        srcDate = srcDate.replace(" ", CommonConstant.EMPTY);
        try {
            // 尝试将源日期字符串标准化处理
            srcDate = doStandard(srcDate);
        } catch (Exception e) {
            // 标准化失败，直接返回源字符串
            return srcDate;
        }

        // 分割标准化后的日期字符串以便处理
        String[] newDate = srcDate.split(CommonConstant.SPLIT_LINE);
        StringBuilder ansDate = new StringBuilder();

        // 处理年份部分
        for (char num : newDate[0].toCharArray()) {
            ansDate.append(ConvertUtils.formatDigit(num - CommonConstant.CHAR_DIGITS[0]));
        }
        ansDate.append(DateConstant.UNIT_YEAR);

        // 处理月份部分
        String getMonth = ConvertUtils.doTransForMonthAndDay(newDate[1]);
        ansDate.append(getMonth);
        ansDate.append(DateConstant.UNIT_MONTH);

        // 处理日份部分
        String getDay = ConvertUtils.doTransForMonthAndDay(newDate[2]);
        ansDate.append(getDay);
        ansDate.append(DateConstant.UNIT_DAY);

        // 返回构建好的格式化日期字符串
        return ansDate.toString();
    }


    /**
     * 中文日期标准化，例如：二零二二年四月九日->2022年4月9日
     *
     * @param str 目标要素
     * @return 转化后的要素内容
     */
    private static String chineseDateStandardization(String str) {
        // 现将 0oO〇 -> 零
        str = str.replaceAll(DateConstant.AREA_UNIT_REGEX, CommonConstant.SIMPLE_DIGITS[0]);
        // 号 -> 日
        str = str.replaceAll(DateConstant.UNIT_HAO, DateConstant.UNIT_DAY);

        String yearStr = StrUtil.subBefore(str, DateConstant.UNIT_YEAR, false);
        String monthStr = StrUtil.subBetween(str, DateConstant.UNIT_YEAR, DateConstant.UNIT_MONTH);
        String dayStr;
        // 没有写日字的处理，或者写的是号字的处理
        if (str.contains(DateConstant.UNIT_DAY)) {
            dayStr = StrUtil.subBetween(str, DateConstant.UNIT_MONTH, DateConstant.UNIT_DAY);
        } else {
            dayStr = StrUtil.subAfter(str, DateConstant.UNIT_MONTH, true);
        }

        String[] years = yearStr.split(CommonConstant.EMPTY);
        StringBuilder sb = new StringBuilder();
        for (String year : years) {
            sb.append(Convert.chineseToNumber(year));
        }

        int month = Convert.chineseToNumber(monthStr);
        int day = Convert.chineseToNumber(dayStr);

        // 为了防止十八这种简写，正常应该是一十八
        if (StrUtil.contains(monthStr, CommonConstant.TEN)) {
            month += 10;
        }
        if (StrUtil.contains(dayStr, CommonConstant.TEN) && day < CommonConstant.TWENTY) {
            day += 10;
        }

        return sb.append(DateConstant.UNIT_YEAR)
                .append(month)
                .append(DateConstant.UNIT_MONTH)
                .append(day)
                .append(DateConstant.UNIT_DAY)
                .toString();
    }


    /**
     * 计算时间戳和当前时间的时间差几天
     *
     * @param timestamp 时间戳
     * @return 天数
     */
    public static int getDays(long timestamp) {
        Instant instant = Instant.now(); // 获取当前时间戳
        Instant instant1 = Instant.ofEpochMilli(timestamp * 1000); // 将时间戳转换为Instant
        Duration duration = Duration.between(instant1, instant); // 计算两个时间之间的时长
        return (int) duration.toDays(); // 将时长转换为天数
    }

    /**
     * 日期标准化标准
     *
     * @param dateStr str日期
     * @return {@code String}
     */
    public static String doStandard(String dateStr) {
        // 汉字的正则
        boolean flag1 = ReUtil.isMatch(DateRegexConstant.CHINESE_DATE_REG, dateStr);
        // 其他正则【可以被hu tool整理的】
        boolean flag2 = ReUtil.isMatch(DateRegexConstant.DATE_REG_LINE, dateStr);
        boolean flag3 = ReUtil.isMatch(DateRegexConstant.DATE_REG_SLASH, dateStr);
        boolean flag4 = ReUtil.isMatch(DateRegexConstant.CHINESE_DATE_REG_NUM, dateStr);
        boolean flag5 = ReUtil.isMatch(DateRegexConstant.DATE_REG_POINT, dateStr);

        if (flag1) {
            // 汉字的日期转成标准日期
            return chineseDateStandardization(dateStr);
        } else if (flag2 || flag3 || flag4 || flag5) {
            // 其他的日期情况，转成标准日期，直接使用hu tool
            return chineseDateConvertLine(dateStr);
        } else {
            return doForSingleUnitAndBottom(dateStr);
        }
    }

    /**
     * 单个单位的日期标准化
     *
     * @param initDate 初始化日期
     * @return 转换结果
     */
    private static String doForSingleUnitAndBottom(String initDate) {
        if (ReUtil.isMatch(DateRegexConstant.ONLY_YEAR, initDate)) {
            return doForSingleYear(initDate);
        } else if (ReUtil.isMatch(DateRegexConstant.ONLY_MONTH, initDate)) {
            return doForSingleCommon(initDate, DateConstant.UNIT_MONTH);
        } else if (ReUtil.isMatch(DateRegexConstant.ONLY_DAY, initDate)) {
            return doForSingleDay(initDate);
        } else if (ReUtil.isMatch(DateRegexConstant.ONLY_HOUR, initDate)) {
            return doForSingleHour(initDate);
        } else if (ReUtil.isMatch(DateRegexConstant.ONLY_MINUTE, initDate)) {
            return doForSingleCommon(initDate, DateConstant.UNIT_MINUTE);
        } else if (ReUtil.isMatch(DateRegexConstant.ONLY_SECOND, initDate)) {
            return doForSingleCommon(initDate, DateConstant.UNIT_SECOND);
        } else {
            // 兜底策略
            return theBottomStrategy(initDate);
        }
    }

    /**
     * 万能兜底策略
     *
     * @param initDate 初始化日期
     * @return 结果
     */
    private static String theBottomStrategy(String initDate) {
        // 号 -> 天
        // 点 -> 时
        initDate = initDate.replace(DateConstant.UNIT_HAO, DateConstant.UNIT_DAY);
        initDate = initDate.replace(CommonConstant.SPLIT_CHN_POINT, DateConstant.UNIT_ONLY_HOUR);

        Map<String, String> ans = new HashMap<>();
        // 年 ？
        if (initDate.contains(DateConstant.UNIT_YEAR)) {
            ans.put(DateConstant.UNIT_YEAR, StrUtil.subBefore(initDate, DateConstant.UNIT_YEAR, false));
            initDate = StrUtil.subAfter(initDate, DateConstant.UNIT_YEAR, false);
        }
        // 月 ？
        if (initDate.contains(DateConstant.UNIT_MONTH)) {
            ans.put(DateConstant.UNIT_MONTH, StrUtil.subBefore(initDate, DateConstant.UNIT_MONTH, false));
            initDate = StrUtil.subAfter(initDate, DateConstant.UNIT_MONTH, false);
        }
        // 日 ？
        if (initDate.contains(DateConstant.UNIT_DAY)) {
            ans.put(DateConstant.UNIT_DAY, StrUtil.subBefore(initDate, DateConstant.UNIT_DAY, false));
            initDate = StrUtil.subAfter(initDate, DateConstant.UNIT_DAY, false);
        }
        // 时 ？
        if (initDate.contains(DateConstant.UNIT_ONLY_HOUR)) {
            ans.put(DateConstant.UNIT_ONLY_HOUR, StrUtil.subBefore(initDate, DateConstant.UNIT_ONLY_HOUR, false));
            initDate = StrUtil.subAfter(initDate, DateConstant.UNIT_ONLY_HOUR, false);
        }
        // 分 ？
        if (initDate.contains(DateConstant.UNIT_MINUTE)) {
            ans.put(DateConstant.UNIT_MINUTE, StrUtil.subBefore(initDate, DateConstant.UNIT_MINUTE, false));
            initDate = StrUtil.subAfter(initDate, DateConstant.UNIT_MINUTE, false);
        }
        // 秒 ？
        if (initDate.contains(DateConstant.UNIT_SECOND)) {
            ans.put(DateConstant.UNIT_SECOND, StrUtil.subBefore(initDate, DateConstant.UNIT_SECOND, false));
        }
        return doTransAll(ans);
    }

    /**
     * 全部进行转换
     *
     * @param map map
     * @return 结果
     */
    private static String doTransAll(Map<String, String> map) {
        // 准备进行封装
        StringBuilder sbd = new StringBuilder();
        // 年月日时分秒
        StringBuilder sbdOfYear = doForEach(DateConstant.UNIT_YEAR, map);
        // 年
        if (map.containsKey(DateConstant.UNIT_YEAR)) {
            if (sbdOfYear.toString().equals(CommonConstant.EMPTY)) {
                return CommonConstant.EMPTY;
            } else {
                sbd.append(sbdOfYear);
            }
        }
        // 月
        StringBuilder sbdOfMonth = doForEach(DateConstant.UNIT_MONTH, map);
        if (map.containsKey(DateConstant.UNIT_MONTH)) {
            if (sbdOfMonth.toString().equals(CommonConstant.EMPTY)) {
                return CommonConstant.EMPTY;
            } else {
                sbd.append(sbdOfMonth);
            }
        }
        // 日
        StringBuilder sbdOfDay = doForEach(DateConstant.UNIT_DAY, map);
        if (map.containsKey(DateConstant.UNIT_DAY)) {
            if (sbdOfDay.toString().equals(CommonConstant.EMPTY)) {
                return CommonConstant.EMPTY;
            } else {
                sbd.append(sbdOfDay);
            }
        }
        // 小时
        StringBuilder sbdOfHour = doForEach(DateConstant.UNIT_ONLY_HOUR, map);
        if (map.containsKey(DateConstant.UNIT_ONLY_HOUR)) {
            if (sbdOfHour.toString().equals(CommonConstant.EMPTY)) {
                return CommonConstant.EMPTY;
            } else {
                sbd.append(sbdOfHour);
            }
        }
        // 分
        StringBuilder sbdOfMinute = doForEach(DateConstant.UNIT_MINUTE, map);
        if (map.containsKey(DateConstant.UNIT_MINUTE)) {
            if (sbdOfMinute.toString().equals(CommonConstant.EMPTY)) {
                return CommonConstant.EMPTY;
            } else {
                sbd.append(sbdOfMinute);
            }
        }
        // 秒
        StringBuilder sbdOfSecond = doForEach(DateConstant.UNIT_SECOND, map);
        if (map.containsKey(DateConstant.UNIT_SECOND)) {
            if (sbdOfSecond.toString().equals(CommonConstant.EMPTY)) {
                return CommonConstant.EMPTY;
            } else {
                sbd.append(sbdOfSecond);
            }
        }
        return sbd.toString();
    }

    /**
     * 每一个转换一下
     *
     * @param unit 单位
     * @param map  map映射
     */
    private static StringBuilder doForEach(String unit, Map<String, String> map) {
        StringBuilder sbd = new StringBuilder();
        if (map.containsKey(unit)) {
            String ans = map.get(unit);
            if (ReUtil.isMatch(ToolRegexConstant.NUMBER_REGEX, ans)) {
                if (unit.equals(DateConstant.UNIT_YEAR) && ans.length() == 2) {
                    sbd.append(DateConstant.YEAR_OF_TWENTY).append(ans).append(unit); // 年的特殊处理，补上"20";
                } else {
                    sbd.append(Integer.parseInt(ans)).append(unit);
                }
            } else {
                // 繁体 -> 简体
                ans = ans.replaceAll(DateConstant.AREA_UNIT_REGEX, CommonConstant.SIMPLE_DIGITS[0]);
                ans = ConvertUtils.transAllBigToSmall(ans);
                if (DateConstant.UNIT_YEAR.equals(unit)) {
                    sbd.append(doStandardForChineseYear(ans));
                } else {
                    // 其他的正常处理
                    ans = ConvertUtils.convertChineseToNum(ans);
                    if (!ans.equals("0")) {
                        sbd.append(ans).append(unit);
                    }
                }
            }
        }
        return sbd;
    }

    /**
     * 年的具体处理逻辑
     *
     * @param initDate 年
     * @return 结果
     */
    private static String doForSingleYear(String initDate) {
        initDate = initDate.replace(DateConstant.UNIT_YEAR, CommonConstant.EMPTY);
        if (ReUtil.isMatch(ToolRegexConstant.NUMBER_REGEX, initDate)) {
            if (initDate.length() == 2) {
                return DateConstant.YEAR_OF_TWENTY + initDate + DateConstant.UNIT_YEAR;
            } else {
                return initDate + DateConstant.UNIT_YEAR;
            }
        } else {
            // 现将 0oO〇 -> 零
            initDate = initDate.replaceAll(DateConstant.AREA_UNIT_REGEX, CommonConstant.SIMPLE_DIGITS[0]);
            // 大写 -> 小写
            initDate = ConvertUtils.transAllBigToSmall(initDate);
            return doStandardForChineseYear(initDate);
        }
    }

    /**
     * common logic for single
     *
     * @param initDate init date
     * @return standard ans
     */
    private static String doForSingleCommon(String initDate, String unit) {
        if (judgeRoundNumber(initDate)) {
            return initDate;
        }
        initDate = initDate.replace(unit, CommonConstant.EMPTY);
        if (ReUtil.isMatch(ToolRegexConstant.NUMBER_REGEX, initDate)) {
            return initDate + unit;
        } else {
            // 现将 0oO〇 -> 零
            initDate = initDate.replaceAll(DateConstant.AREA_UNIT_REGEX, CommonConstant.SIMPLE_DIGITS[0]);
            // 汉字 -> 数字
            return ConvertUtils.convertChineseToNum(initDate) + unit;
        }
    }

    /**
     * 日的具体处理逻辑
     *
     * @param initDate 日
     * @return 结果
     */
    private static String doForSingleDay(String initDate) {
        if (judgeRoundNumber(initDate)) {
            return initDate;
        }
        initDate = initDate.replace(DateConstant.UNIT_DAY, CommonConstant.EMPTY);
        initDate = initDate.replace(DateConstant.UNIT_HAO, CommonConstant.EMPTY);
        if (ReUtil.isMatch(ToolRegexConstant.NUMBER_REGEX, initDate)) {
            return initDate + DateConstant.UNIT_DAY;
        } else {
            // 现将 0oO〇 -> 零
            initDate = initDate.replaceAll(DateConstant.AREA_UNIT_REGEX, CommonConstant.SIMPLE_DIGITS[0]);
            // 汉字 -> 数字
            return ConvertUtils.convertChineseToNum(initDate) + DateConstant.UNIT_DAY;
        }
    }

    /**
     * 时的具体处理逻辑
     *
     * @param initDate 时
     * @return 结果
     */
    private static String doForSingleHour(String initDate) {
        if (judgeRoundNumber(initDate)) {
            return initDate;
        }
        initDate = initDate.replace(DateConstant.UNIT_ONLY_HOUR, CommonConstant.EMPTY);
        initDate = initDate.replace(CommonConstant.SPLIT_CHN_POINT, CommonConstant.EMPTY);
        if (ReUtil.isMatch(ToolRegexConstant.NUMBER_REGEX, initDate)) {
            return initDate + DateConstant.UNIT_ONLY_HOUR;
        } else {
            // 现将 0oO〇 -> 零
            initDate = initDate.replaceAll(DateConstant.AREA_UNIT_REGEX, CommonConstant.SIMPLE_DIGITS[0]);
            // 汉字 -> 数字
            return ConvertUtils.convertChineseToNum(initDate) + DateConstant.UNIT_ONLY_HOUR;
        }
    }

    /**
     * 判断提出来的数是不是概数
     *
     * @param s 字符串
     * @return 如果是概数 -> true, 没有找到这些关键词 -> false
     */
    private static boolean judgeRoundNumber(String s) {
        for (String round : DateConstant.ROUND_NUMBER_FLAG) {
            if (s.contains(round)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 汉字标准化年，兼容两位数
     *
     * @param initDate 日期
     * @return 结果
     */
    private static String doStandardForChineseYear(String initDate) {
        initDate = initDate.replace(CommonConstant.BIG_THOUSAND, CommonConstant.THOUSAND);
        // 年的特殊处理，可能口语化表述
        if (DateConstant.MAP_OF_YEAR.containsKey(initDate)) {
            return DateConstant.MAP_OF_YEAR.get(initDate) + DateConstant.UNIT_YEAR;
        }
        if (initDate.length() == 2) {
            initDate = "二零" + initDate;
        }
        // 转换后返回
        return convertChineseToArabicYear(initDate) + DateConstant.UNIT_YEAR;
    }

    /**
     * 年份转成阿拉伯数字
     * 例如：二零零二 -> 2002
     *
     * @param chineseYear 汉字的年
     * @return 结果
     */
    private static int convertChineseToArabicYear(String chineseYear) {
        HashMap<Character, Integer> chineseNumMap = new HashMap<>();
        chineseNumMap.put('零', 0);
        chineseNumMap.put('一', 1);
        chineseNumMap.put('二', 2);
        chineseNumMap.put('三', 3);
        chineseNumMap.put('四', 4);
        chineseNumMap.put('五', 5);
        chineseNumMap.put('六', 6);
        chineseNumMap.put('七', 7);
        chineseNumMap.put('八', 8);
        chineseNumMap.put('九', 9);

        int[] weights = {1, 10, 100, 1000};
        int arabicYear = 0;
        int index = 0;

        for (int i = chineseYear.length() - 1; i >= 0; i--) {
            char chineseNum = chineseYear.charAt(i);
            int num = chineseNumMap.get(chineseNum);
            arabicYear += num * weights[index];
            index++;
        }
        return arabicYear;
    }
}